package com.library.common.config;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 自定义异步方法执行
 *
 * @author: xyh
 * @create: 2023-07-21
 **/
@Slf4j
@EnableAsync
@Configuration
@RequiredArgsConstructor
public class AsyncConfiguration implements AsyncConfigurer {


    /**
     * Java虚拟机可用的处理器数
     */
    private final int cpus = Runtime.getRuntime().availableProcessors();

    /**
     * 定义线程池,  ThreadPoolTaskExecutor不是完全被IOC容器管理的bean,可以在方法上加上@Bean注解交给容器管理
     * @return
     */
    @Bean(name = "taskExecutor")
    public ThreadPoolTaskExecutor taskExecutor() {
        final String threadNamePrefix = "taskExecutor-";
        //定义线程池
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程池大小，默认 8
        executor.setCorePoolSize(cpus);
        // 最大线程数，默认 Integer.MAX_VALUE
        executor.setMaxPoolSize(cpus * 2);
        // 队列容量，默认 Integer.MAX_VALUE
        executor.setQueueCapacity(Integer.MAX_VALUE);
        // 拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 线程名前缀
        executor.setThreadNamePrefix(threadNamePrefix);
        //线程池中线程最大空闲时间，默认：60，单位：秒
        executor.setKeepAliveSeconds(60);
        //IOC容器关闭时是否阻塞等待剩余的任务执行完成，默认:false
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //阻塞IOC容器关闭的时间，默认：10秒
        executor.setAwaitTerminationSeconds(10);
        executor.initialize();
        return executor;
    }

    /**
     * 返回配置好的线程池
     * @return
     */
    @Override
    public Executor getAsyncExecutor() {
        return this.taskExecutor();
    }

    /**
     * 异步方法执行的过程中抛出的异常捕获
     * @return
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (throwable, method, objects) -> {
            log.error("[异步任务线程池] 执行异步任务【{}】时出错 >> 堆栈\t\n", method.getDeclaringClass(), throwable);
        };
    }
}
